﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Xml.Serialization;
using ICSharpCode.SharpZipLib.Zip;
using Microsoft.Win32;
using PivotLibrary;
using System.Drawing;
using System.Drawing.Imaging;

namespace SampleHelper
{
    public class Helper
    {

        internal static List<ItemInfo> ScanAllSamples(bool saveToFile)
        {
            List<ItemInfo> samples = new List<ItemInfo>();
            foreach (var dir in Directory.GetDirectories(Settings.SamplesFolder))
            {
                string infoFilePath = dir + "\\" + Settings.InfoFilename;
                if (File.Exists(infoFilePath))
                {
                    string filePath = dir + "\\" + Settings.InfoFilename;
                    using (FileStream stream = File.Open(filePath, FileMode.Open))
                    {
                        ItemInfo info = null;
                        try
                        {
                            XmlSerializer serializer = new XmlSerializer(typeof(ItemInfo));
                            info = (ItemInfo)serializer.Deserialize(stream);
                        }
                        catch
                        {
                            MessageBox.Show("Error in info.xml: " + filePath);
                            continue;
                        }

                        // Demo Name
                        string dirname = dir.Substring(dir.LastIndexOf("\\") + 1);
                        if (info.Name == string.Empty || info.Name == null)
                        {
                            info.Name = dirname;
                        }

                        // Screenshot
                        string screenshotFile = dir + "\\" + Settings.ScreenshotFilename;
                        if (File.Exists(screenshotFile))
                        {
                            info.Screenshot = screenshotFile;
                        }

                        // Presentation
                        string presentationFile = dir + "\\" + Settings.PresentationFileName;
                        if (File.Exists(presentationFile))
                        {
                            info.AddProperty(TextResource.PowerPoint, "../apps/" + dirname + "/" + Settings.PresentationFileName);
                        }

                        // tutorial
                        string docFile = dir + "\\" + Settings.TutorialFilename;
                        if (File.Exists(docFile))
                        {
                            info.AddProperty(TextResource.TutorialLabel, "../apps/" + dirname + "/" + Settings.TutorialFilename);
                        }

                        // Source
                        string zipFile = dir + "\\" + Settings.SourceFile;
                        if (File.Exists(zipFile))
                        {
                            string filename = Path.GetFileName(zipFile);
                            info.AddProperty(TextResource.SourceCode, "../apps/" + dirname + "/" + filename);
                        }

                        // 
                        // Material 
                        // 

                        samples.Add(info);
                    }
                }
            }


            string path = Settings.SampleIndexFile;
            if (File.Exists(path))
            {
                File.Delete(path);
            }

            using (StreamWriter stream = File.CreateText(path))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(List<ItemInfo>));
                serializer.Serialize(stream, samples);
                stream.Close();
            }

            return samples;
        }

        internal static void CreateTemplateInfoFile()
        {
            ItemInfo si = new ItemInfo();
            si.Name = "Template Sample";
            si.Description = "Just a sample description";

            List<string> keys = new List<string>() { "Powerpoint", "Video", "Tutorial" };

            foreach (var k in keys)
            {
                si.AddProperty(k, "One");
                si.AddProperty(k, "Two");
                si.AddProperty(k, "Three");
            }
            si.Screenshot = "abc.png";

            SaveFileDialog sfd = new SaveFileDialog();
            if (sfd.ShowDialog().Value)
            {
                using (StreamWriter stream = File.CreateText(sfd.FileName))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(ItemInfo));
                    serializer.Serialize(stream, si);
                }
            }
        }

        public static void GenerateDeepZoomImages(
            List<ItemInfo> samples,
            string deepZoomPath,
            bool overrideExistingImages,
            bool createDeepZoom)
        {

            if (!Directory.Exists(deepZoomPath))
            {
                Directory.CreateDirectory(deepZoomPath);
            }

            List<string> correctImages = new List<string>();
            List<string> filterProperties = new List<string>();

            DeepZoomHelper dzh = new DeepZoomHelper();

            foreach (var sample in samples)
            {
                string url = sample.Screenshot;

                // Create dz image
                var dzi = dzh.CreateSingleImage(
                    deepZoomPath,
                    "output",
                    url,
                    sample.Name,
                    overrideExistingImages);

                if (File.Exists(dzi))
                {
                    correctImages.Add(dzi);
                }
                else
                {
                    Console.WriteLine("File does not exist: " + dzi);
                }
            }

            if (createDeepZoom)
            {
                dzh.CreateCollection(correctImages, deepZoomPath + "output");
            }

        }

        public static void CreatePivotFile(string deepZoomOutputPath, List<ItemInfo> samples)
        {
            string pivotIndexFile = deepZoomOutputPath + "index.cxml";

            Collection collection = new Collection();
            collection.EnableInfoPaneBingSearch = true;
            collection.Name = "Windows Client Demos";

            foreach (var sample in samples)
            {
                List<Facet> facets = new List<Facet>();
                string filename = DeepZoomHelper.CreateCleanFilename(sample.Name);
                string imagePath = deepZoomOutputPath + "output_images\\" + Path.GetFileNameWithoutExtension(filename) + ".xml";

                ItemImage itemImage = new ItemImage(imagePath);

                Dictionary<string, List<string>> linksFacets = new Dictionary<string, List<string>>();
                Dictionary<string, List<string>> tagFacets = new Dictionary<string, List<string>>();

                foreach (var k in sample.GetKeys())
                {
                    if (sample.GetProperties(k) != null)
                    {
                        bool isLink = false;
                        foreach (var t in sample.GetProperties(k))
                        {
                            if (t.ToLower().StartsWith("http") ||
                                t.ToLower().EndsWith(".pptx") ||
                                t.ToLower().EndsWith(".docx") ||
                                t.ToLower().EndsWith(".zip")
                                )
                            {
                                isLink = true;
                            }

                            if (isLink)
                            {
                                List<string> linkList;
                                if (!linksFacets.ContainsKey(k))
                                {
                                    linkList = new List<string>();
                                    linksFacets.Add(k, linkList);
                                }
                                else
                                {
                                    linkList = linksFacets[k];
                                }

                                //List<FacetHyperlink> links = new List<FacetHyperlink>();
                                //FacetHyperlink fh = new FacetHyperlink(k, t);
                                //links.Add(fh);
                                linkList.Add(t);

                                //facets.Add(facet);
                            }
                            else
                            {

                                List<string> tagList;
                                if (!tagFacets.ContainsKey(k))
                                {
                                    tagList = new List<string>();
                                    tagFacets.Add(k, tagList);
                                }
                                else
                                {
                                    tagList = tagFacets[k];
                                }

                                tagList.Add(t);

                            }
                            //tags.Add(t);

                        }
                    }
                }

                // Add Links
                List<FacetHyperlink> links = new List<FacetHyperlink>();
                foreach (var key in linksFacets.Keys)
                {
                    foreach (string link in linksFacets[key])
                    {
                        FacetHyperlink fh = new FacetHyperlink(key, link);
                        links.Add(fh);
                    }
                }
                Facet facetLink = new Facet("Links", links.ToArray());
                facets.Add(facetLink);

                // add Tags
                foreach (var key in tagFacets.Keys)
                {
                    List<string> tags = new List<string>();
                    foreach (string t in tagFacets[key])
                    {
                        tags.Add(t);
                    }
                    Facet facet = new Facet(key, tags.ToArray());
                    facets.Add(facet);
                }

                collection.AddItem(
                    sample.Name,
                    sample.Url,
                    sample.Description,
                    itemImage,
                    facets.ToArray());
            }

            collection.EnableInfoPaneBingSearch = true;

            collection.ToCxml(pivotIndexFile);

            // Fix: missing ImgBase="output.xml" 
            string xml = string.Empty;
            using (StreamReader sr = File.OpenText(pivotIndexFile))
            {
                xml = sr.ReadToEnd();
                xml = xml.Replace("<Items>", "<Items ImgBase=\"output.xml\">");
                xml = xml.Replace(" xmlns=\"\"", "");
            }
            File.Delete(pivotIndexFile);
            File.WriteAllText(pivotIndexFile, xml);
        }

        internal static void CreateProjectZipFile()
        {
            foreach (var dir in Directory.GetDirectories(Settings.ProjectsDirectory))
            {
                string dirname = dir.Substring(dir.LastIndexOf(Path.DirectorySeparatorChar) + 1);
                ZipFolder(dir, Settings.SamplesFolder + dirname + "\\" + Settings.SourceFile);
            }
        }

        private static void ZipFolder(string sourcedir, string targetfile)
        {
            ZipFiles(sourcedir, targetfile, string.Empty);
        }

        public static void ZipFiles(string inputFolderPath, string outputPathAndFile, string password)
        {
            ArrayList ar = GenerateFileList(inputFolderPath); // generate file list
            int TrimLength = (Directory.GetParent(inputFolderPath)).ToString().Length;

            // find number of chars to remove 	// from orginal file path
            TrimLength += 1; //remove '\'
            FileStream ostream;
            byte[] obuffer;

            //string outPath = inputFolderPath + @"\" + outputPathAndFile;
            string outPath = outputPathAndFile;

            // Folder Check
            string folder = outputPathAndFile.Substring(0, outputPathAndFile.LastIndexOf("\\"));
            if (!Directory.Exists(folder))
            {
                MessageBox.Show("Folder does not exist: " + folder);
                return;
            }

            ZipOutputStream oZipStream = new ZipOutputStream(File.Create(outPath)); // create zip stream
            if (password != null && password != String.Empty)
                oZipStream.Password = password;
            oZipStream.SetLevel(9); // maximum compression
            ZipEntry oZipEntry;
            foreach (string Fil in ar) // for each file, generate a zipentry
            {
                oZipEntry = new ZipEntry(Fil.Remove(0, TrimLength));
                oZipStream.PutNextEntry(oZipEntry);

                if (!Fil.EndsWith(@"/")) // if a file ends with '/' its a directory
                {
                    ostream = File.OpenRead(Fil);
                    obuffer = new byte[ostream.Length];
                    ostream.Read(obuffer, 0, obuffer.Length);
                    oZipStream.Write(obuffer, 0, obuffer.Length);
                }
            }
            oZipStream.Finish();
            oZipStream.Close();
        }

        private static ArrayList GenerateFileList(string Dir)
        {
            ArrayList fils = new ArrayList();

            if (Dir.ToLower().EndsWith("bin"))
            {
                return fils;
            }

            bool Empty = true;
            foreach (string file in Directory.GetFiles(Dir)) // add each file in directory
            {
                fils.Add(file);
                Empty = false;
            }

            if (Empty)
            {
                if (Directory.GetDirectories(Dir).Length == 0)
                // if directory is completely empty, add it
                {
                    fils.Add(Dir + @"/");
                }
            }

            foreach (string dirs in Directory.GetDirectories(Dir)) // recursive
            {
                foreach (object obj in GenerateFileList(dirs))
                {
                    fils.Add(obj);
                }
            }
            return fils; // return file list
        }


        internal static void CreateSampleHtmlPage()
        {
            List<ItemInfo> samples = Helper.ScanAllSamples(true);

            string htmlPage = Settings.WebFolder;

            htmlPage += "demos";

            string htmlTemplatePage = htmlPage + "_template.htm";
            htmlPage += ".htm";

            if (File.Exists(htmlPage))
            {
                File.Delete(htmlPage);
            }

            string text = File.ReadAllText(htmlTemplatePage);

            string html = string.Empty;

            foreach (var sample in samples)
            {
                html += Environment.NewLine;
                html += "<h2>" + sample.Name + "</h2>";
                html += Environment.NewLine;
                html += "<table>";

                // Beschreibung
                if (sample.Description != null && sample.Description.Length > 0)
                {
                    html += "<tr>";
                    // Screenshot
                    html += "<td valign=\"top\">";
                    // Screenshot
                    if (sample.Screenshot != null && sample.Screenshot.Length > 0)
                    {
                        // Copy Thumbnail to folder
                        if (!Directory.Exists(Settings.WebFolderForThumbs))
                        {
                            Directory.CreateDirectory(Settings.WebFolderForThumbs);
                        }

                        string thumbnailName = sample.Name.Replace(" ", "") + Path.GetExtension(sample.Screenshot);
                        string absoluteThumbnailPath = Settings.WebFolderForThumbs + thumbnailName;
                        string relativThumbnailPath = "thumbs/" + thumbnailName;
                        CreateThumbnail(sample.Screenshot, absoluteThumbnailPath);

                        html += Environment.NewLine;
                        //html += "<img src=\"" + sample.Screenshot + "\" style=\"width:320px;\" alt=\"Screenshot " + sample.Name + " \"/>";
                        html += "<img src=\"" + relativThumbnailPath + "\" alt=\"Screenshot " + sample.Name + " \"/>";
                        html += Environment.NewLine;
                        html += Environment.NewLine;
                    }
                    else
                    {
                        html += "&nbsp;";
                    }
                    html += "</td>";

                    // Description
                    html += "<td valign=\"top\">" + sample.Description + "</td>";
                    html += "</tr>";
                    html += Environment.NewLine;
                }
                html += "</table>";

                // Eigenschaften
                Dictionary<string, List<string>> groupedProperties = sample.GetGroupedProperties();
                if (sample.Properties != null && groupedProperties.Count > 0)
                {
                    html += "<p>";

                    foreach (var k in groupedProperties.Keys)
                    {
                        html += k + "<br />";
                        html += Environment.NewLine;
                        int i = 0;
                        foreach (var prop in groupedProperties[k])
                        {
                            if (i > 0)
                            {
                                html += ", ";
                            }
                            i++;
                            if (prop.ToLower().StartsWith("http"))
                            {
                                html += "<a href=\"" + prop + "\" target=\"_new\" >Link</a>";
                            }
                            else
                            {
                                html += prop;
                            }                  
                        }
                        html += Environment.NewLine;
                        html += "<br />";
                    }
                    html += "</p>";
                    html += Environment.NewLine;
                }
                
            }

            
            text = text.Insert(text.IndexOf("<body>") + 6, html);

            File.WriteAllText(htmlPage, text);
        }

        private static void CreateThumbnail(string source, string target)
        {
            Image image = Bitmap.FromFile(source);

            Image thumbnailImage = image.GetThumbnailImage(160, 120, new Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);

            // make a memory stream to work with the image bytes
            if (File.Exists(target))
            {
                File.Delete(target);
            }
            using (FileStream file = new FileStream(target, FileMode.CreateNew))
            {
                thumbnailImage.Save(file, ImageFormat.Jpeg);
            }
            
        }

        public static bool ThumbnailCallback()
        {
            return true;
        }
    }
}
